package cn.jiangjiesheng.bootstrap.fileport.infrastructure.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;


/**
 * 日期转换
 *
 * Created by luzaiqiang on 19-11-11.
 */
@Slf4j
public class DateUtils {

    public static final String DEFAULT_DATETIMEFORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATETIMEFORMAT2 = "yyyyMMddHHmmss";
    public static final String DEFAULT_DATEFORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_TIMEFORMAT = "HH:mm";
    public static final String DEFAULT_DATEMINFORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_DATEHOURFORMAT = "yyyy-MM-dd HH";
    public static final int DAY = 1000 * 3600 * 24;
    public static final long MIN = 1000 * 60;

    public static final String TIMESTAMP_FORMAT_STRING_T = "yyyy-MM-dd'T'HH:mm:ss";


    public static String YYYY_MM_DD_000000 = "yyyy-MM-dd 00:00:00";
    public static String YYYY_MM_DD_235959 = "yyyy-MM-dd 23:59:59";


    /**
     * 将时间格式化指定的格式, 返回String
     *
     * @param date
     * @param format
     * @return
     */
    public static String dateFormatToString(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 将时间格式指定为 yyyy-MM-dd ,返回String
     *
     * @param date
     * @return
     */
    public static String dateFormatToDateString(Date date) {
        return dateFormatToString(date, DEFAULT_DATEFORMAT);
    }

    /**
     * 将时间格式指定为 yyyy-MM-dd HH:mm ,返回String
     *
     * @param date
     * @return
     */
    public static String dateFormatToDATEMINFORString(Date date) {
        return dateFormatToString(date, DEFAULT_DATEMINFORMAT);
    }

    /**
     * 将时间格式指定为 yyyy-MM-dd HH:mm:ss,返回String
     *
     * @param date
     * @return
     */
    public static String dateFormatToDateYYYYMMDDHHMISS(Date date) {
        return dateFormatToString(date, DEFAULT_DATETIMEFORMAT);
    }

    /**
     * 将时间格式指定为 yyyy-MM-dd HH:mm:ss,返回String
     *
     * @param date
     * @return
     */
    public static String dateFormatToDateYYYYMMDDHHMISS2(Date date) {
        return dateFormatToString(date, DEFAULT_DATETIMEFORMAT2);
    }

    /**
     * 将时间格式化指定的格式, 返回Date
     *
     * @param date
     * @param format
     * @return
     * @throws ParseException
     */
    public static Date dateFormatToDate(Date date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(sdf.format(date));
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化失败:" + format + "\n" + e.toString());
        }
    }

    /**
     * 将时间Date  格式化成date类型 yyyy-MM-dd
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date dateFormatToDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATEFORMAT);
        try {
            return sdf.parse(sdf.format(date));
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化失败:" + DEFAULT_DATEFORMAT + "\n" + e.toString());
        }
    }

    /**
     * 将yyyy-MM-dd HH:mm:ss 格式字符串转换成时间
     *
     * @param dateStr
     * @return
     * @throws ParseException
     */
    public static Date formatDate(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATETIMEFORMAT);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化失败:" + dateStr + "\n" + e.toString());
        }
    }

    /**
     * 将String 格式字符串转换成时间
     *
     * @param dateStr
     * @return
     * @throws ParseException
     */
    public static Date formatDate(String dateStr, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化失败:" + dateStr + "\n" + e.toString());
        }
    }

    /**
     * 将yyyy-MM-dd 格式字符串转换成时间
     *
     * @param dateStr
     * @return
     * @throws ParseException
     */
    public static Date formatDateYMD(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATEFORMAT);
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期格式化失败:" + dateStr + "\n" + e.toString());
        }
    }

    /**
     * 两个日期的天数差(不足一天按0天算)
     *
     * @param date1
     * @param date2
     * @return int
     */
    public static int dateDiff(Date date1, Date date2) {
        long diff = date1.getTime() - date2.getTime();
        int d = (int) Math.floor((double) Math.abs(diff) / DAY);
        return d > 0 ? d : (0 - d);
    }

    /**
     * 两个日期的时间比较大小(取日期+时间比较)
     *
     * @param date1
     * @param date2
     * @return int
     */
    public static int dateTimeDiff(Date date1, Date date2) {
        long diff = date1.getTime() - date2.getTime();
        return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
    }

    /**
     * 获取datetime 时间
     * yyyy-MM-dd HH:mm:ss ---- HH:mm
     *
     * @param date
     * @return int
     */
    public static String dateTime2Time(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_TIMEFORMAT);
        return sdf.format(date);
    }

    /**
     * 两个日期的分钟数差
     *
     * @param date1
     * @param date2
     * @return int
     */
    public static int dateTimeMinus(Date date1, Date date2) {
        long diff = date1.getTime() - date2.getTime();
        int d = (int) Math.floor((double) Math.abs(diff) / MIN);
        return Math.abs(d);
    }

    /**
     * date 时间计算
     *
     * @param date         时间点
     * @param calendarType 间隔类型(Calendar.*)
     * @param interval     时间间隔
     * @return
     */
    public static Date calculateDate(Date date, int calendarType, int interval) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(calendarType, calendar.get(calendarType) + interval);
        return calendar.getTime();
    }

    /**
     * 转换时区
     *
     * @param sourceDate       源日期
     * @param sourceTimeZone   源时区，formats: <ul> <li>{@code +hh:mm} <li>{@code -hh:mm} </ul>
     * @param targetTimeZoneId 目标时区
     * @return 目标时区的日期
     */
    public static Date convertToZone(Date sourceDate, String sourceTimeZone, ZoneId targetTimeZoneId) {
        ZoneOffset zoneOffsetSource = ZoneOffset.of(sourceTimeZone);// 源时区
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(sourceDate.toInstant(), ZoneId.systemDefault());// 此处zoneOffsetSource无用，后面会重新设置
        // 切换为源时区
        zonedDateTime = zonedDateTime.withZoneSameLocal(zoneOffsetSource);
        // 切换为目标时区
        zonedDateTime = zonedDateTime.withZoneSameInstant(targetTimeZoneId);
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 转为当地北京时间
     *
     * @param sourceDate     源日期
     * @param sourceTimeZone 源时区，formats: <ul> <li>{@code +hh:mm} <li>{@code -hh:mm} </ul>
     * @return 服务器当地的时间
     */
    public static Date parseZoneToLocal(Date sourceDate, String sourceTimeZone) {
        String dateStr = dateFormatToString(sourceDate, TIMESTAMP_FORMAT_STRING_T);
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateStr + sourceTimeZone, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * 获取日期为星期几
     *
     * @param date
     * @return
     */
    public static int getDateWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        Integer[] weeks = {7, 1, 2, 3, 4, 5, 6};
        int week_index = calendar.get(Calendar.DAY_OF_WEEK) - 1;

        return weeks[week_index];
    }

    public static Date getDateBeforeMonth(Date currentDate, Integer beforMonths) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.MONTH, -beforMonths);
        return calendar.getTime();
    }

    public static String getDaysBefore(int daysBefore) {
        LocalDateTime now = LocalDateTime.now();
        now = now.minus(daysBefore, ChronoUnit.DAYS);

        Date date = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
        return DateUtils.dateFormatToDateYYYYMMDDHHMISS(date);
    }

    private static String getDateFormat(String dateFormatType,Date date) {
        SimpleDateFormat simformat = new SimpleDateFormat(dateFormatType);
        return simformat.format(date);
    }

    public static String formatCSTTime(String format,String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
        Date d = sdf.parse(date);
        return getDateFormat(format,d);
    }

    /*
     * 将格式化时间转换为时间戳
     */
    public static String dateToStamp(String s) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String res = "";
        if (!"".equals(s)) {
            try {
                res = String.valueOf(sdf.parse(s).getTime() / 1000);
            } catch (Exception e) {
                log.info("传入了null值");
            }
        } else {
            long time = System.currentTimeMillis();
            res = String.valueOf(time / 1000);
        }

        return res;
    }


    public static Date getDate(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        Date date = Date.from(zonedDateTime.toInstant());
        return date;
    }

    public static String getDateString(LocalDate localDate) {
        Date date = getDate(localDate);

        return dateFormatToDateYYYYMMDDHHMISS(date);
    }

    public static String getDateString(LocalDate localDate, String format) {
        Date date = getDate(localDate);

        return dateFormatToString(date, format);
    }


    /**
     * 获取当天开始时间
     */
    public static String dayStartTime() {
        return DateFormatUtils.format(new Date(), DateUtils.YYYY_MM_DD_000000);
    }

    /**
     * 获取当天结束时间
     */
    public static String dayEndTime() {
        return DateFormatUtils.format(new Date(), DateUtils.YYYY_MM_DD_235959);
    }


    public static String getDateStringNow() {
        return dateFormatToString(new Date(), DEFAULT_DATETIMEFORMAT);
    }


}
